﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;

namespace Models
{
    public class GameTimer
    {

        public delegate void Update(GameTimer timer);
        public delegate void Render(World world);
        public event Update UpdateEvent;
        public event Render RenderEvent;

        private Stopwatch stopWatch;
        private Thread stopWatchThread;
        private int tickTime;
        private World world;

        public GameTimer(World world, int tickTime)
        {
            this.world = world;
            stopWatch = new Stopwatch();
            IsRunning = true;

            stopWatchThread = new Thread(
                () => {
                    //main tick loop
                    while (IsRunning)
                    {
                        if (stopWatch.ElapsedMilliseconds >= tickTime)
                        {
                            LastTickTime = stopWatch.ElapsedMilliseconds;
                            GameTotalMilliseconds += LastTickTime;

                            DelayFactor = LastTickTime / (float)tickTime;

                            stopWatch.Restart();
                            internalTick();
                            GameTotalTicks++;
                        }
                        else
                        {
                            long sleepTime = tickTime - stopWatch.ElapsedMilliseconds;
                            Thread.Sleep(sleepTime > 0 ? (int)sleepTime : 1);
                        }
                    }
                }
            );
        }

        public bool IsRunning { get; set; }
        public long GameTotalMilliseconds { get; private set; }
        public long GameTotalTicks { get; private set; }
        public long LastTickTime { get; private set; }
        public float DelayFactor { get; private set; }

        public void Start()
        {
            stopWatch.Start();
            stopWatchThread.Start();
        }

        private void internalTick()
        {
            UpdateEvent(this);
            RenderEvent(world);
        }
    }
}
